/**
*@namespace sv2gl
*/
var sv2gl = {
/**
* @class Game
* @constructor {Game}
* @param {String} fps: The frames per second for the game
* This is the main class for creating a game.  This class contains the SceneController and InputController for the game
* and upon executing the run command will start the physics engine and load all the game objects.  If the current scene
* does not have a world it will create a baseline world for you.
*/
	Game:function(args){
		var me = this;
		/**
		* This is the main access point to add scenes to the game
		*/
		this.SceneControl = new sv2gl.SceneController();
		/**
		* This is the main access point to add inputs to the game
		*/
		this.InputControl = new sv2gl.InputController();		
		var PhysicsEngine = null;
		/**
		* This begins the game by creating an instance of the physics engine and loading all the game objects from the initial scene.
		*/
		this.run = function(){
			if(me.SceneControl.getCurrentScene() !== null &&typeof me.SceneControl.getCurrentScene() !== 'undefined'){
				if(me.SceneControl.getCurrentScene().world === null || typeof me.SceneControl.getCurrentScene().world === 'undefined'){
					me.SceneControl.getCurrentScene().world = new physics.world();
				}
				PhysicsEngine = new physics.Engine({fps:1000/args.fps, sceneController:me.SceneControl, world:me.SceneControl.getCurrentScene().world});
				me.SceneControl.loadScene(me.SceneControl.getCurrentScene().id);
				PhysicsEngine.run();
			}
		};
	},
	/**
	*@class InputController
	*@constructor {InputController}
	* This provides an easy way to add a player to the game and also to add and change input methods to the game.
	*/
	InputController:function(){
		var player;
		/**
		* @param {GameObject} player: the player of the game
		* This method sets the player for the game for easy retrieval later
		*/
		this.setPlayer = function(args){
			player = args.gameObject;
		};
		/**
		* This method gets the player for the game 
		*/
		this.getPlayer = function(){
			return player;
		};
		/**
		* @param {Event} onkeypress: the function that will be fired onkeypress
		* This method sets the onkeypress method for the document
		*/
		this.setonkeypress = function(args){
			document.onkeypress(args.onkeypress);
		};
		
		/**
		* @param {Event} onmouseover: the function that will be fired onmouseover
		* This method sets the onmouseover method for the document
		*/
		this.setonmouseover= function(args){
			document.onmouseover(args.onmouseover);
		};
		
		/**
		* @param {Event} onmouseout: the function that will be fired onmouseout
		* This method sets the onmouseout method for the document
		*/
		this.setonmouseout = function(args){
			document.onmouseout(args.onmouseout);
		};
	},
	/**
	*@class SceneController
	*@constructor {SceneController}
	* This is the controller that controls the scenes within a game.  It provides easy access to add scenes and 
	* instantiate them via id.
	*/
	SceneController:function() {
		var me = this;
		var scenes = [{}];
		var currentSceneId = null;
		/**
		* This will add a scene to the scenes json object using the passed in scene's id as it's key
		* @param {Scene} scene: The scene object to be added
		*/
		this.addScene = function(scene){
			scenes[scene.id] =scene;
		};
		/**
		* This will load a scene as the current scene based on the id passed in
		* @param {Number} sceneId: The id of the scene to be loaded
		*/
		this.loadScene = function(sceneId){
			//TODO Throws
			currentSceneId = sceneId;
			scenes[sceneId].load();
		};
		/**
		* This will destroy the current scene
		*/
		this.destroyScene = function(){
			//TODO Throws
			scenes[currentSceneId].destroy();
		};
		/**
		* This will retrieve the current scene
		*/
		this.getCurrentScene = function(){
			return scenes[currentSceneId];
		};
		/**
		* This will set the current scene
		* @param {Scene} scene: the scene to be set as the current scene
		*/
		this.setCurrentScene = function(scene){
			currentSceneId = scene.id;
		};	
		/**
		* This will retrieve the current scene
		* @param {String} sceneId: the id of the scene to be loaded
		*/
		this.getScene = function(sceneId){
			return scenes[sceneId];
		};
	},
	/**
	*@class GameObjectController
	*@constructor {GameObjectController}
	* This is the controller that controls the game objects within a scene.
	*/
	GameObjectController:function() {
		var objects = [];
		var objectsKeyValue=[{}];
		/**
		* This method adds a gameObject to the controller
		* @param {GameObject} gameObject: The game object to be added to the controller
		*/
		this.addObject = function(gameObject){
			objectsKeyValue[gameObject.id] = gameObject;
			objects.push(objectsKeyValue[gameObject.id]);
		};
		/**
		* This method loads all objects into the dom that are in the controller
		*/
		this.loadObjects  = function(){
			for(var x = 0; x < objects.length;x++){
				objects[x].load();
			}
		};
		/**
		* This method destroys all objects in the dom that are in the controller
		*/
		this.destroyObjects  = function(){
			for(var x = 0; x < objects.length;x++){
				objects[x].destroy();
			}
		};
		/**
		* This method returns all objects in the controller
		*/
		this.getObjects = function(){
			return objects;
		};
		/**
		* This method gets an object by it's id from the controller
		* @param {String} id: the id of the game object to be retrieved 
		*/
		this.getObjectById = function(id){
			return objectsKeyValue[id];
		};
	},
	/**
	*@class {Scene} Scene
	*@constructor {Scene}
	*@param {String} id: the id of the scene
	*@param {Event} onUpdate:the onUpdate method for the scene.  This is called every frame.
	*@param {Event} onExit:the onExit method for the scene. This method is called when the scene is destroyed
	*@param {Event} world:the world for the scene. This determines where the physics engine checks for collision.
	* This is the scene object. It contains the game object controller and the world used by the physics engine.
	*/
	Scene:function(args)
	{
		
		var me = this;
		/**
		* This is the id of the scene.  
		*/
		this.id = args.id;
		/**
		* This is the GameObjectController for the scene.  It controls all the objects in the scene.
		*/
		this.GameObjectControl = new sv2gl.GameObjectController();
		/**
		* This is the onUpdate method for the scene. This method is called every frame.
		*/
		this.onUpdate = args.onUpdate;
		/**
		* This is the onLoad method for the scene. This method is called when the load method is called for the scene.
		*/
		this.onLoad = args.onLoad;
		/**
		* This is the onExit for the scene.  This method is called when the destroy method is called for the scene.
		*/
		this.onExit = args.onExit;
		var updateInterval;
		/**
		* This is the world for the scene.  This determines where collision and gravity get applied in the scene.
		*/
		this.world = args.world;
		/**
		* This method loads the scene.  It calls the onLoad method and begins the onUpdate interval based on the Fps passed into the original game.
		* This also loads all the game objects for the scene via the GameObjectControl object.
		*/
		this.load = function(){
			if(me.onLoad !== null && typeof me.onLoad !== 'undefined'){
				me.onLoad(me);
			}
			if(me.onUpdate !== null && typeof me.onUpdate !== 'undefined'){
				updateInterval = setInterval(function() { me.onUpdate(me); }, Fps);
			}
			me.GameObjectControl.loadObjects();
		};
		/**
		* This method destroys the scene.  It calls the onExit method and cancels the onUpdate interval.
		* It also destroys all game objects in the scene via the GameObjectControl object.
		*/
		this.destroy = function(){
			if(me.onExit !== null && typeof me.onExit !== 'undefined'){
				me.onExit(me);
			}
			if(updateInterval !== null && typeof updateInterval !== 'undefined'){
				clearInterval(updateInterval);
			}
			me.GameObjectControl.destroyObjects();
		};
	},
	/**
	*@class {GameObject} GameObject
	*@constuctor {GameObject}  
	*@param {String} id: the id of the GameObject
	*@param {Number} x: the x position of the GameObject
	*@param {Number} y: the y position of the GameObject
	*@param {Number} z: the z position of the GameObject
	*@param {Number} height:the height of the GameObject
	*@param {Number} width:the width of the GameObject
	*@param {SpriteSheet} spriteSheet:the spriteSheet of the GameObject
	*@param {AnimationController} animationControl:the AnimationController for the GameObject	
	*@param {Event} onUpdate: the onUpdate method that is run every frame
	*@param {Event} onLoad: the onLoad method that is run when the load method is called
	*/
	GameObject:function(args){
		var me = this;
		/**
		*
		*/
		this.id = args.id;
		var x = args.x;
		var y = args.y;
		var z = args.z;
		var height = args.height;
		var width = args.width;
		this.spriteSheet = args.spriteSheet;
		this.animationControl = new sv2gl.AnimationController({parent:me});
		var animationX = args.x;
		var animationY = args.y;
		this.onUpdate = args.onUpdate;
		this.onLoad = args.onLoad;
		this.onExit = args.onExit;
		this.onClick = args.onClick;
		args["src"] = me.spriteSheet.src; 
		this.element = svg.createElement(args);
		this.updateInterval;
		this.collisionBox = args.collisionBox;
		var transform = args.transform;
		if(transform === null || typeof transform === 'undefined'){
			transform = new physics.Transform({translateX:0,translateY:0,rotateAngle:0,rotateCx:0,rotateCy:0});
		}

		this.load = function(){
			svg.appendElement(me.element);
			me.setTransform(transform);
			svg.transformElement(transform, me.element);
			svg.setElementAttribute({element:me.element,attribute:"clip-path", value:"url(#"+me.spriteSheet.id+")"});	
			if(me.onLoad !== null &&typeof me.onLoad !== 'undefined'){
				me.onLoad(me);
			}
			if(me.onClick !== null &&typeof me.onClick !== 'undefined'){
				svg.setElementAttribute({"attribute":"onclick", "value":me.onClick ,element:me.element});
			}
			
			me.startUpdate();
		};
		this.clearUpdate = function(){
			if(me.updateInterval !== null && typeof me.updateInterval !== "undefined"){
				me.clearInterval(me.updateInterval);
			}
		};
		this.startUpdate = function(){
			if(me.onUpdate !== null && typeof me.onUpdate !== "undefined"){
				me.updateInterval = setInterval(function() { me.onUpdate(me); }, 30);
			}
		};
		this.destroy = function(){
			if(me.onExit !== null && typeof me.onExit !== "undefined"){
				me.onExit(me);
			}
			me.clearUpdate();
			svg.removeElement(me.element);
		};
		this.setX = function(newX){
			if(me.collisionBox !== null || typeof me.collisionBox !== 'undefined'){
				me.collisionBox.x += newX - x;
			}
			x = newX;
			
			svg.setElementAttribute({element:me.spriteSheet.element,attribute:"x",value:x });
			svg.setElementAttribute({"attribute":"x", "value":x,element:me.element});
		};
		this.setY = function(newY){
			if(me.collisionBox !== null || typeof me.collisionBox !== 'undefined'){
				me.collisionBox.y += newY - y;
			}
			y = newY;
			svg.setElementAttribute({element:me.spriteSheet.element,attribute:"y",value:y });
			svg.setElementAttribute({"attribute":"y", "value":y,element:me.element});
		};
		this.setZ = function(newZ){
			if(me.collisionBox !== null || typeof me.collisionBox !== 'undefined'){
				me.collisionBox.z += newZ - z;
			}
			z = newZ;
			svg.setElementAttribute({"attribute":"z", "value":z ,element:me.element});
		};
		this.setHeight = function(newH){
			height = newH;
			svg.setElementAttribute({"attribute":"height", "value":height,element:me.element});
		};
		this.setWidth = function(newW){
			width = newW;
			svg.setElementAttribute({"attribute":"width", "value":width ,element:me.element});
		};
		this.setOnClick = function(newOnClick){
			me.onClick = newOnClick;
			svg.setElementAttribute({"attribute":"onclick", "value":me.onClick ,element:me.element});
		};
		this.setAnimationX = function(newX){
			animationX = newX;
			svg.setElementAttribute({"attribute":"x", "value":animationX,element:me.element});
		};
		this.setAnimationY = function(newY){
			animationY = newY;
			svg.setElementAttribute({"attribute":"y", "value":animationY,element:me.element});
		};
		this.setTransform = function(newTransform){
			transform = newTransform;
			if(me.collisionBox !== null || typeof me.collisionBox !== 'undefined'){
				me.collisionBox.transform = newTransform;
			}
			svg.transformElement(transform, me.element);
		};
		this.getX = function(){
			return x;
		};
		this.getY = function(){
			return y;
		};
		this.getZ = function(){
			return z;
		};
		this.getHeight = function(){
			return height;
		};
		this.getWidth = function(){
			return width;
		};
		this.getElement = function(){
			return element;
		};
		this.getAnimationX = function(){
			return animationX;
		};
		this.getAnimationY = function(){
			return animationY;
		};
		this.getTransform = function(){
			return transform;
		};
		this.getTransformedX = function(){
			return transform.transformX(x, y);
		};
		this.getTransformedY = function(){
			return transform.transformY(x, y);
		};
		this.getOnClick = function(){
			return onClick;
		};
		this.addTransform = function(newTransform){
			transform.add(newTransform);
			if(me.collisionBox !== null || typeof me.collisionBox !== 'undefined'){
				me.collisionBox.add(newTransform);
			}
		};
	},
	AnimationController:function(args){
		var me = this;
		var animations = [{}];
		var currentAnimationId = '';
		this.parent = args.parent;
		
		this.setAnimationOriginalX = function(newX){
			for(var x in animations)
			{
				animations[x].setOriginalX(newX);
			}
		};
		this.setAnimationOriginalY = function(newY){
			for(var x in animations)
			{
				animations[x].setOriginalY(newY);
			}
		};
		this.addAnimation = function(animation){
			animation.parent = me.parent;
			animations[animation.id] =animation;
		};
		
		this.startAnimation = function(animationId){
			//TODO Throws
			currentAnimationId = animationId;
			animations[animationId].start();
		};
		
		this.stopAnimation = function(){
			//TODO Throws
			animations[animationId].stop();
		};
		
		this.getAnimation = function(animationId){
			return animations[animationId];
		};
	},
	Animation:function(args){
		var me = this;
		var frames = [];
		var currentFrameIndex = 0;
		var interval;
		this.id = args.id;
		this.looped = args.looped;
		this.speed =  args.speed;
		this.parent;
		this.addFrame = function(frame){
			frames.push(frame);
		};
		this.start = function(){
			me.parent.spriteSheet.setCurrentFrame(frames[currentFrameIndex].id, me.parent.getAnimationX() , me.parent.getAnimationY());
			me.parent.setAnimationX(me.parent.getX() - frames[currentFrameIndex].x);
			me.parent.setAnimationY(me.parent.getY() - frames[currentFrameIndex].y);
			currentFrameIndex++;
			interval = setInterval(step, me.speed);
		};
		this.stop = function(){
			clearInterval(interval);
			currentFrameIndex = 0;
		};
		this.getFrame = function(frameIndex){
			return frames[frameIndex];
		};
		var step = function(){
			var start = new Date();
			if(currentFrameIndex < frames.length -1)
			{
				me.parent.spriteSheet.setCurrentFrame(frames[currentFrameIndex].id, me.parent.getAnimationX() , me.parent.getAnimationY());
				me.parent.setAnimationX(me.parent.getX() - frames[currentFrameIndex].x);
				me.parent.setAnimationY(me.parent.getY() - frames[currentFrameIndex].y);
				currentFrameIndex++;
			}
			else if(me.looped){
				currentFrameIndex = 0;
				me.parent.spriteSheet.setCurrentFrame(frames[currentFrameIndex].id, me.parent.getAnimationX() , me.parent.getAnimationY());
				me.parent.setAnimationX(me.parent.getX() - frames[currentFrameIndex].x);
				me.parent.setAnimationY(me.parent.getY() - frames[currentFrameIndex].y);
				currentFrameIndex++;
			}
			else{
				me.stop();
			}
			var end = new Date();
			console.log("Step:"+(end-start));
		};
		
	},
	SpriteSheet:function(args){
		var me = this;
		this.src = args.src;
		this.id = args.id;
		this.parentElement = svg.createClipPathElement(this);
		svg.appendElement(this.parentElement);
		var frames = [{}];
		var currentFrame = args.initialFrame;
		frames[currentFrame.id] = currentFrame;
		args.initialFrame.parentClipPath = this.parentElement;
		this.element = svg.createPathElement(args.initialFrame);

		this.addFrame = function(frame){
			frames[frame.id] = frame;
		};
		this.getFrame = function(id){
			return frames[id];
		};
		this.getCurrentFrame = function(){
			return currentFrame;
		};
		this.setCurrentFrame = function(id){
			currentFrame = frames[id];
			svg.setElementAttribute({element:me.element,attribute:"height",value: currentFrame.height});
			svg.setElementAttribute({element:me.element,attribute:"width",value: currentFrame.width});
		};
	},
	Frame:function(args){
		this.x = args.x;
		this.id = args.id;
		this.y = args.y;
		this.height = args.height;
		this.width = args.width;
	}
};
var svg = {
		svgns: "http://www.w3.org/2000/svg",
		appendElement:function(element){
			document.getElementsByTagName("svg")[0].appendChild(element);
		},
		removeElement:function(element){
			element.parentNode.removeChild(element);
		},
		setElementAttribute:function(args){
			if(args.attribute == "xlink:href")
			{
				args.element.setAttributeNS("http://www.w3.org/1999/xlink",args.attribute, args.value);
			}
			else{
				args.element.setAttributeNS(null,args.attribute, args.value);
			}
		},
		findElement:function(args){
			return document.getElementById(args.id);
		},
		createElement:function(args){
			var img = document.createElementNS(svg.svgns, "image");
			img.setAttributeNS(null, "x", args.x);
			img.setAttributeNS(null, "y", args.y );
			img.setAttributeNS(null, "z",args.z);
			img.setAttributeNS(null, "height",args.height);
			img.setAttributeNS(null, "width",args.width);
			img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", args.src);
			img.setAttributeNS(null, "id",args.id);
			img.setAttributeNS(null, "image-rendering", "optimizeSpeed");
			img.setAttributeNS(null, "preserveAspectRatio", "none");
			img.setAttributeNS(null, "transform", "translate(0,0) rotate(0)");
			return img;
		},
		createClipPathElement:function(args){
			var clip = document.createElementNS(svg.svgns, "clipPath");
			clip.setAttributeNS(null, "id",args.id);
			return clip;
		},
		createPathElement:function(args){
			var path = document.createElementNS(svg.svgns, "rect");
			path.setAttributeNS(null, "x", args.x);
			path.setAttributeNS(null, "y", args.y );
			path.setAttributeNS(null, "height",args.height);
			path.setAttributeNS(null, "width",args.width);
			path.setAttributeNS(null, "transform", "translate(0,0) rotate(0)");
			args.parentClipPath.appendChild(path);
			return path;
		},
		transformElement:function(args, element){
			var x = args.translateX;
			var y = args.translateY;
			var angle = args.rotateAngle;
			var cy = args.rotateCy;
			var cx = args.rotateCx;
			var value = "translate(" + x +"," + y + ") rotate(" + angle + "," + cx+"," + cy+")";
			svg.setElementAttribute({"attribute":"transform", "value": value, element:element});
		}
};

var physics = {
	Engine:function(args){
		var me = this;
		this.world = args.world;
		var CollisionEngine;
		var fps = args.fps;
		var sceneController = args.sceneController;
		var updateInterval;
		this.run = function(){
			CollisionEngine = new physics.CollisionEngine({sceneController:sceneController, world:me.world});
			updateInterval = setInterval(me.recalculateFrame, fps);
		};
		this.recalculateFrame = function(){
			me.recalculateGravity();
			CollisionEngine.recalculateCollision();
		};
		this.recalculateGravity = function(){
			var start = new Date();
			var currentScene = sceneController.getCurrentScene();
			var objects = currentScene.GameObjectControl.getObjects();
			for(var i = 0; i < objects.length;i++){
				var obj = objects[i];
				if(obj.collisionBox.type == "Mobile"){
					obj.setY(obj.getY() + me.world.gravity);
				}
			}
		};
	},
	CollisionEngine:function(args){
		var me = this;
		var sceneControl = args.sceneController;
		var engineWorld = args.world;
		var sectorSize = 500;
		this.recalculateCollision = function()
		{
			var start = new Date();
			var currentScene = sceneControl.getCurrentScene();
			var objects = currentScene.GameObjectControl.getObjects();
			var spatialHash = [];
			var sectorRadius = (Math.sqrt(Math.pow(sectorSize, 2) * 2));
			var sectorCenterX = sectorSize/2;
			var sectorCenterY = sectorSize/2; 
			//Create spatial hash
			//This gets the x boundary, makes it evenly divisible by sector size then divides by sector size
			var xMod = engineWorld.width % sectorSize;
			var columns;
			if(xMod === 0){
				columns = engineWorld.width/sectorSize;
			}
			else{
				columns = ((engineWorld.width - xMod)/sectorSize) + 1;
			}
			
			var yMod = engineWorld.length % sectorSize;
			var rows;
			if(yMod === 0){
				rows = engineWorld.length/sectorSize;
			}
			else{
				rows = ((engineWorld.length - yMod)/sectorSize) + 1;
			}
			
			//now find out which bucket to place in
			for(var i = 0; i < objects.length;i++){
				var collision = objects[i].collisionBox;
				var parentObject = objects[i];
				if(collision !== null && typeof collision !== "undefined" && collision.active){
					var x1 = collision.x;
					var y1 = collision.y;
					var x2 = collision.x + collision.width;
					var y2 = collision.y + collision.length;
					var xValues = [];
					var yValues = [];
					xValues.push(collision.transform.transformX(x1, y1));
					xValues.push(collision.transform.transformX(x1, y2));
					xValues.push(collision.transform.transformX(x2, y1));
					xValues.push(collision.transform.transformX(x2, y2));
					yValues.push(collision.transform.transformY(x1, y1));
					yValues.push(collision.transform.transformY(x1, y2));
					yValues.push(collision.transform.transformY(x2, y1));
					yValues.push(collision.transform.transformY(x2, y2));
					var xMin=null;
					var yMin=null; 
	
					for(var v = 0; v < xValues.length;v++){
						if(xMin === null && yMin === null){
							xMin=xValues[v];
							yMin=yValues[v]; 						
						}
						if(xValues[v] < xMin){
							xMin=xValues[v];
						}
						if(yValues[v] < yMin){
							yMin=yValues[v];
						}
					}
					
					var collCenterX = xMin + collision.width/2;   
					var collCenterY = yMin + collision.length/2;
					
					var collRadius = Math.sqrt(Math.pow(collision.width, 2) + Math.pow(collision.length, 2));
					
					var columns = [];
					var rows = [];
					
					var row1 = (collCenterX +collRadius - ((collCenterX +collRadius)%sectorSize))/sectorSize; 
					var row2 = (collCenterX - collRadius - ((collCenterX - collRadius)%sectorSize))/sectorSize;
					
					var col1 = (collCenterY +collRadius - ((collCenterY +collRadius)%sectorSize))/sectorSize; 
					var col2 = (collCenterY - collRadius - ((collCenterY- collRadius)%sectorSize))/sectorSize;
					
					rows.push(row1);
					if(row1 != row2){
						rows.push(row2);
					}
					columns.push(col1);
					if(col1 != col2){
						columns.push(col2);
					}
					
					
					//Not adjacent
					if(row2 != row1 -1){
						for(var t = row2;t < row1;t++){
							rows.push(t);
						}
					}
					
					if(col2 != col1 -1){
						for(var t = col2;t < col1;t++){
							columns.push(t);
						}
					}
					
					for(var x = 0; x < columns.length;x++){
						var column = columns[x];
						if(column+1 > spatialHash.length){
							for(var b = 0; b < column+1;b++){
								var newCol = [];
								spatialHash.push(newCol);
							}
						}
						for(var y= 0; y < rows.length;y++){
							var row = rows[y];
							if(row+1 > spatialHash[column].length){
								for(var c = 0; c < row+1;c++){
									var newRow = [];
									spatialHash[column].push(newRow);
								}
							}
							if(column < spatialHash.length && row < spatialHash[column].length)
							{
								spatialHash[column][row].push(parentObject);
							}
						}
					}
				}
			}//End of spatial hash
			//Collision checking
			for(var z = 0; z < spatialHash.length;z++){
				for(var a = 0; a < spatialHash[z].length;a++){
					var objects = spatialHash[z][a];
					for(var b = 0; b < objects.length;b++){
						var obj1 = objects[b].collisionBox;
						var radius1 = Math.sqrt(Math.pow(obj1.width, 2) + Math.pow(obj1.length, 2))/2;
						var centerX1 = obj1.x + obj1.width/2;
						var centerY1 = obj1.y + obj1.length/2;
						for(var c = b + 1; c < objects.length;c++){
							var obj2 = objects[c].collisionBox;
							if((obj1.type != "Stationary" || obj2.type != "Stationary")){  
								if(obj1.z == obj2.z){
									var radius2 = Math.sqrt(Math.pow(obj2.width, 2) + Math.pow(obj2.length, 2))/2;		
									var centerX2 = obj2.x + obj2.width/2;
									var centerY2 = obj2.y + obj2.length/2;
									var distance = Math.sqrt(Math.pow(centerX2 - centerX1, 2) + Math.pow(centerY2 - centerY1, 2)) 
									if(distance <= radius1 + radius2){
										checkCollision(objects[b],objects[c]);
									}
								}
							}
						}
					}
				}
			}
			var end = new Date();
			console.log(end - start);
		};
		var checkCollision = function(obj1Parent, obj2Parent){
			var inverseAngle;
			var obj1;
			var obj2;
			if((obj1Parent.collisionBox.length * obj1Parent.collisionBox.width) > (obj1Parent.collisionBox.length * obj1Parent.collisionBox.width))
			{										
				obj2 = obj1Parent.collisionBox;
				obj1 = obj2Parent.collisionBox;
			}
			else
			{
				obj1 = obj1Parent.collisionBox;
				obj2 = obj2Parent.collisionBox;
		
			}
			if(obj1.transform.rotateAngle < 0){
				inverseAngle = obj1.transform.rotateAngle;
			}
			else{
				inverseAngle = -obj1.transform.rotateAngle;
			}
			var compensateRotation = new physics.Transform({translateX:obj1.transform.translateX,translateY:obj1.transform.translateY,rotateAngle:inverseAngle,rotateCx:obj1.transform.rotateCx,rotateCy:obj1.transform.rotateCy});
			var o1x1 = compensateRotation.transformX(obj1.transform.transformX(obj1.x, obj1.y),obj1.transform.transformY(obj1.x, obj1.y));
			var o1x2 = compensateRotation.transformX(obj1.transform.transformX(obj1.x+obj1.length, obj1.y),obj1.transform.transformY(obj1.x+obj1.length, obj1.y));
			var o1y1 = compensateRotation.transformY(obj1.transform.transformX(obj1.x, obj1.y),obj1.transform.transformY(obj1.x, obj1.y));
			var o1y2 = compensateRotation.transformY(obj1.transform.transformX(obj1.x, obj1.y+obj1.width),obj1.transform.transformY(obj1.x, obj1.y+obj1.width));
			compensateRotation.translateX = 0;
			compensateRotation.translateY = 0;
			var point1 = [compensateRotation.transformX(obj2.transform.transformX(obj2.x, obj2.y),obj2.transform.transformY(obj2.x, obj2.y)), compensateRotation.transformY(obj2.transform.transformX(obj2.x, obj2.y),obj2.transform.transformY(obj2.x, obj2.y)) ];
			var point2 = [compensateRotation.transformX(obj2.transform.transformX(obj2.x+obj2.length, obj2.y),obj2.transform.transformY(obj2.x+obj2.length, obj2.y)), compensateRotation.transformY(obj2.transform.transformX(obj2.x+obj2.length, obj2.y),obj2.transform.transformY(obj2.x+obj2.length, obj2.y))];
			var point3 = [compensateRotation.transformX(obj2.transform.transformX(obj2.x, obj2.y+obj2.width),obj2.transform.transformY(obj2.x, obj2.y + obj2.width)),compensateRotation.transformY(obj2.transform.transformX(obj2.x, obj2.y+obj2.width),obj2.transform.transformY(obj2.x, obj2.y + obj2.width))];
			var point4 = [compensateRotation.transformX(obj2.transform.transformX(obj2.x+obj2.length, obj2.y + obj2.width),obj2.transform.transformY(obj2.x+obj2.length, obj2.y + obj2.width)),compensateRotation.transformY(obj2.transform.transformX(obj2.x+obj2.length, obj2.y + obj2.width),obj2.transform.transformY(obj2.x+obj2.length, obj2.y + obj2.width))];	
			var points = [ point1,point2,point3,point4 ];
			
			var isColliding = false;
			
			for(var e = 0; e < points.length;e++){
				var x = points[e][0];
				var y =points[e][1];
				
				if(x <= o1x2 && x >= o1x1 && y <= o1y2 && y >= o1y1){
					var prjx1 = o1x2 - x;
					var prjx2 = x - o1x1;
					var prjy1 = o1y2 - y;
					var prjy2 = y - o1y1;
					var prjx;
					var prjy;
					if(prjx1 < prjx2)
					{
						prjx = prjx1;
					}
					else
					{
						prjx = prjx2;
					}
					if(prjy1 < prjy2)
					{
						prjy = prjy1;
					}
					else
					{
						prjy = prjy2;
					}

					var dp;
					if(prjy < prjx || prjx == 0){
						if(obj1.type == "Mobile")
						{
							dp = prjx * obj1Parent.getX() + prjy * obj1Parent.getY();
							if(Math.abs(obj1.y - obj2.y) < Math.abs(obj1.y - obj2.y + obj2.length))
							{
								obj1Parent.setY(obj1Parent.getY() - (dp/(Math.pow(obj1Parent.getX(),2) + Math.pow(obj1Parent.getY(),2)))*obj1Parent.getY());
							}
							else
							{
								obj1Parent.setY(obj1Parent.getY() + (dp/(Math.pow(obj1Parent.getX(),2) + Math.pow(obj1Parent.getY(),2)))*obj1Parent.getY());
							}
						}
						else if(obj2.type == "Mobile")
						{
							dp = prjx * obj2Parent.getX() + prjy * obj2Parent.getY();
							if(Math.abs(obj2.y - obj1.y) < Math.abs(obj2.y - obj1.y + obj1.length))
							{
								obj2Parent.setY(obj2Parent.getY() - (dp/(Math.pow(obj2Parent.getX(),2) + Math.pow(obj2Parent.getY(),2)))*obj2Parent.getY());
							}
							else
							{
								obj2Parent.setY(obj2Parent.getY() + (dp/(Math.pow(obj2Parent.getX(),2) + Math.pow(obj2Parent.getY(),2)))*obj2Parent.getY());
							}
						}
					}
					else{
						if(obj1.type == "Mobile")
						{
							dp = prjx * obj1Parent.getX() + prjy * obj1Parent.getY();
						
							if(Math.abs(obj1.x - obj2.x) < Math.abs(obj1.x - obj2.x + obj2.width))
							{
								obj1Parent.setX(obj1Parent.getX() - xMultip*(dp/(Math.pow(obj1Parent.getX(),2) + Math.pow(obj1Parent.getY(),2)))*obj1Parent.getX());
							}
							else
							{
								obj1Parent.setX(obj1Parent.getX() + xMultip*(dp/(Math.pow(obj1Parent.getX(),2) + Math.pow(obj1Parent.getY(),2)))*obj1Parent.getX());
							}
						}
						else if(obj2.type == "Mobile")
						{
							dp = prjx * obj2Parent.getX() + prjy * obj2Parent.getY();
							
							if(Math.abs(obj2.x - obj1.x) < Math.abs(obj2.x - obj1.x + obj1.width))
							{
								obj2Parent.setX(obj2Parent.getX() - xMultip*(dp/(Math.pow(obj2Parent.getX(),2) + Math.pow(obj2Parent.getY(),2)))*obj2Parent.getX());
							}
							else
							{
								obj2Parent.setX(obj2Parent.getX() + xMultip*(dp/(Math.pow(obj2Parent.getX(),2) + Math.pow(obj2Parent.getY(),2)))*obj2Parent.getX());								
							}
						}
					}	
					break;
				}
			}
		};
	},
	CollisionBox:function(args){
		this.length = args.length;
		this.width = args.width;
		this.x = args.x;
		this.y = args.y;
		this.z = args.z;
		this.type = args.type;
		this.active = true;
		this.transform = args.transform;
	},
	World:function(args){
		var me = this;
		this.length;
		this.width;
		this.gravity;
		if(args === null || typeof args === 'undefined'){
			me.length = 10000;
			me.width = 10000;
			me.gravity = 0;
		}
		else
		{
			me.length = args.length;
			me.width = args.width;
			me.gravity = args.gravity;
		}    
	},
	Transform:function(args){
		var me = this;
		this.translateX = args.translateX;
		this.translateY = args.translateY;
		this.rotateAngle = args.rotateAngle;
		this.rotateCx = args.rotateCx;
		this.rotateCy = args.rotateCy;
		//TODO Skew and scale 
		this.transformX = function(x, y){
			var ox = x + me.translateX;
			var oy = y + me.translateY;
			var theta = me.rotateAngle * (Math.PI/180);
			var value = me.rotateCx + (ox - me.rotateCx)*(Math.cos(theta)) - (oy - me.rotateCy)*(Math.sin(theta));
			return value;
		};
		this.transformY = function(x, y){
			var ox = x + me.translateX;
			var oy = y + me.translateY;
			var theta = me.rotateAngle * (Math.PI/180);
			var value = me.rotateCy + (ox - me.rotateCx)*(Math.sin(theta)) + (oy - me.rotateCy)*(Math.cos(theta));
			return value;
		};
		this.add = function(transform){
			me.translateX += transform.translateX;
			me.translateY += transform.translateY;
			me.rotateAngle += transform.rotateAngle;
			me.rotateCx += transform.rotateCx;
			me.rotateCy += transform.rotateCy;
		};
		this.subtract = function(transform){
			me.translateX -= transform.translateX;
			me.translateY -= transform.translateY;
			me.rotateAngle -= transform.rotateAngle;
			me.rotateCx -= transform.rotateCx;
			me.rotateCy -= transform.rotateCy;
		};
	}
}